
var gameenv = {
    rows: 25,
    cols: 25
}

var slip = Math.sqrt(gameenv.rows * gameenv.rows + gameenv.cols * gameenv.cols)
var degree = 0
var processMessage
var speed = 1
var fps = 30
var processFrame
var iterator = function(collection, callback) {
    var it = collection.iterator()
    while (it .hasNext()) {
        var one = it.next()
        var ret = callback(one)
        if (ret === false) {
            break
        }
    }
}

var broadcast = function(msg) {
    game.broadcast(msg)
}

processFrame = function() {
    var clients = game.getClients()
    
    iterator(clients, function(client) {
        if (!client || client == null) {
            return
        }
        var role = client.role
        if (!role || role == null) {
            return
        }
        var auto = role.extras.get("auto")
        if (auto == null) {
            return
        }
        var degree = role.extras.getOrDefault("degree", 0)
        var baseX = role.extras.get("baseX")
        var baseY = role.extras.get("baseY")
        if (baseX == null) {
            baseX = role.pos.x
            role.extras.put("baseX", role.pos.x)
        }
        if (baseY == null) {
            baseY = role.pos.y
            role.extras.put("baseY", role.pos.y)
        }
        var radius = role.extras.get("radius")
        if (radius == null) {
            radius = slip / (Math.floor(Math.random() * 3) + 3)
            role.extras.put("radius", radius)
        }
        var x = Math.floor(Math.cos(degree) * radius + 0.5)
        var y = Math.floor(Math.sin(degree) * radius + 0.5)
        
        degree = degree + (speed / fps) * Math.PI * role.extras.get("clock")
        role.extras.put("degree", degree)

        // 判断是否碰撞
        var collision = false
        var localRoles = game.getRoles()
        iterator(localRoles, function(localRole) {
            if (localRole === role || localRole == null) {
                return
            }
            if (localRole.pos.x === baseX + x && localRole.pos.y === baseY + y) {
                // 碰撞
                // print(localRole.pos.x, localRole.pos.y, baseX + x, baseY + y)
                collision = true
                return false
            }
        })
        
        if (collision) {
            role.extras.put("clock", role.extras.get("clock") * -1)
            return
        }
        // print(slip, dx, dy)
        role.pos.x = Math.floor(degree / Math.PI * radius * 2 + 0.5)
        role.pos.y = baseY + y
        
        if (role.pos.x >= gameenv.cols) {
            role.pos.x = role.pos.x % gameenv.cols
        }
        else {
            role.pos.x = (role.pos.x + gameenv.cols) % gameenv.cols 
        }
        if (role.pos.y >= gameenv.rows) {
            role.pos.y = role.pos.y % gameenv.rows
        }
        else {
            role.pos.y = (role.pos.y + gameenv.rows) % gameenv.rows
        }

        var data = {
            action: "moveto",
            params: {
                pos: {x: role.pos.x, y: role.pos.y},
                userid: role.userid
            }
        }
        
        broadcast(JSON.stringify(data))
    })
}

processMessage = function(client, msg) {
    var json = JSON.parse(msg)
    
    var action = json.action
    var params = json.params
    var userid = params.userid
    if (action == "roleenter") {
        var pos = params.pos
        var init = {
            action: "initgame",
            params: gameenv
        }
        client.send(JSON.stringify(init))
        
        // 同步所有角色
        var roles = game.getRoles()
        iterator(roles, function(role) {
            if (!role || role == null) {
                return
            }
            var data = {
                action: "roleenter",
                params: {
                    pos: {x: role.pos.x, y: role.pos.y},
                    color: role.color,
                    userid: role.userid
                }
            }

            client.send(JSON.stringify(data))
        })
        json.params.pos.x = msg
        json.params.pos.x = Math.floor(gameenv.cols / 2)
        json.params.pos.y = Math.floor(gameenv.rows / 2)
        game.addRole(client.userid, json.params.color, json.params.pos.x, json.params.pos.y)
        if (Math.random() < 0.3) {
            game.getRole(client.userid).extras.put("clock", 1)
            game.getRole(client.userid).extras.put("auto", true)
        }
        msg = JSON.stringify(json)
    }
    else if (action == "move") {
        var vec2 = params.vec2
        var role = game.getRole(userid)
        role.pos.x = role.pos.x + vec2.x
        role.pos.y = role.pos.y + vec2.y
        
        if (role.pos.x >= gameenv.cols) {
            role.pos.x = 0
        }
        if (role.pos.y >= gameenv.rows) {
            role.pos.y = 0
        }
        role.extras.put("baseX", role.pos.x)
        role.extras.put("baseY", role.pos.y)
    }
    broadcast(msg)
}

var processor = {}
processor[1] = processFrame
processor[2] = processMessage

function main(type, client, msg) {
    // console.log(type, client, json)
    processor[type](client, msg)
}

